package com.kgis.map.handler.mouse {
    import com.kgis.map.Map;
    import com.kgis.map.events.MapEvent;
    import com.kgis.map.geometry.basetype.Location;
    import com.kgis.map.geometry.basetype.Pixel;
    import com.kgis.map.handler.Handler;
    import flash.events.Event;
    import flash.events.MouseEvent;

    /**
     * 鼠标拖动地图操作
     */
    public class DragHandler extends Handler {
        private var _startCenter:Location = null;
        private var _start:Pixel = null;
        private var _offset:Pixel = null;

        private var _firstDrag:Boolean = true;

        private var _dragging:Boolean = false;

        //add by hongfly
        private var _lastpix:Pixel = null;

        /**
         *Callbacks function
         */
        private var _onStart:Function = null;
        private var _oncomplete:Function = null;

        /**
         * DragHandler constructor
         *
         * @param map the DragHandler map
         * @param active to determinates if the handler is active (default=true)
         */
        public function DragHandler(map:Map, handlername:String) {
            super(map, handlername);
        }

        override protected function registerListeners():void {
            if (this.map) {
                this.map.addEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
                this.map.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
            }
        }

        override protected function unregisterListeners():void {
            if (this.map) {
                this.map.removeEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
                this.map.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
            }
        }

        /**
         * The MouseDown Listener
         */
        protected function onMouseDown(event:Event):void {
            if (this._dragging)
                return;

            if (_firstDrag) {
                this.map.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
                _firstDrag = false;
            }

            this.map.addEventListener(MouseEvent.MOUSE_MOVE, this.onMouseMove);

            this._start = new Pixel(this.map.mouseX, this.map.mouseY);
            this._lastpix = _start.clone();
            this._offset = new Pixel(this.map.mouseX - this.map.layerContainer.x, this.map.mouseY - this.map.layerContainer.y);
            this._startCenter = this.map.center;
            this.map.buttonMode = true;
            this._dragging = true;
            this.map.dispatchEvent(new MapEvent(MapEvent.DRAG_START, this.map));
            if (this.onstart != null)
                this.onstart(event as MouseEvent);
        }

        protected function onMouseMove(event:MouseEvent):void {
            this.map.layerContainer.x = this.map.mouseX - this._offset.x;
            this.map.layerContainer.y = this.map.mouseY - this._offset.y;
            if (this.map.bitmapTransition) {
                this.map.bitmapTransition.x = this.map.mouseX - this._offset.x;
                this.map.bitmapTransition.y = this.map.mouseY - this._offset.y;
            }

            /*        if(map.selectedFeatures!=null && map.selectedFeatures.length>0){
               trace("--dragmousemove---"+(map.selectedFeatures[0].geometry as PolylineGeometry).pointList.getItemAt(0));
               }
             */
            // Force update regardless of the framerate for smooth drag
            event.updateAfterEvent();

        /*         if(map.selectedFeatures!=null && map.selectedFeatures.length>0){
           var pot:PointGeometry = ((map.selectedFeatures[0].geometry as PolylineGeometry).pointList.getItemAt(0)) as PointGeometry;

           trace("--dragmousemove---"+((map.getLayerPxFromLocation(new Location(pot.x,pot.y))) as Pixel).toString() );
         }*/


        /*	if(this.map.baseLayer){
           if(this.map.baseLayer is Grid){
           if (Math.abs(this._lastpix.x - this.map.mouseX) > (this.map.baseLayer as Grid).tileWidth || Math.abs(this._lastpix.y - this.map.mouseY) > (this.map.baseLayer as Grid).tileHeight ){
           //瓦片图连续拖动，没有白边
           var deltaX:Number = this._start.x - this.map.layerContainer.parent.mouseX;
           var deltaY:Number = this._start.y - this.map.layerContainer.parent.mouseY;

           var newPosition:Location = new Location(this._startCenter.lon + deltaX * this.map.resolution,
           this._startCenter.lat - deltaY * this.map.resolution,
           this._startCenter.projection);

           this._lastpix.x = this.map.mouseX;
           this._lastpix.y = this.map.mouseY;
           (this.map.baseLayer as Grid).moveGriddedTiles(new Bounds(newPosition.lon - this.map.width*this.map.resolution/2 , newPosition.lat - this.map.height * this.map.resolution/2 , newPosition.lon + this.map.width*this.map.resolution/2,newPosition.lat + this.map.height * this.map.resolution/2));
         }}}*/
        }

        /**
         *The MouseUp Listener
         */
        protected function onMouseUp(event:Event):void {
            if ((!this.map))
                return;

            this.map.removeEventListener(MouseEvent.MOUSE_MOVE, this.onMouseMove);
            /*			if(map.selectedFeatures!=null && map.selectedFeatures.length>0){
               trace("---dragmouseup--"+(map.selectedFeatures[0].geometry as PolylineGeometry).pointList.getItemAt(0));
             }*/

            this.map.buttonMode = false;
            this.done(new Pixel(this.map.mouseX, this.map.mouseY));
            // A MapEvent.MOVE_END is emitted by the "set center" called in this.done

            if (this.oncomplete != null)
                this.oncomplete(event as MouseEvent);
        }

        // Getters & setters as3
        /**
         * To know if the map is dragging
         */
        public function get dragging():Boolean {
            return this._dragging;
        }

        public function set dragging(dragging:Boolean):void {
            this._dragging = dragging;
        }

        /**
         * Start's callback this function is call when the drag starts
         */
        public function set onstart(onstart:Function):void {
            this._onStart = onstart;
        }

        public function get onstart():Function {
            return this._onStart;
        }

        /**
         * Stop's callback this function is call when the drag ends
         */
        public function set oncomplete(oncomplete:Function):void {
            this._oncomplete = oncomplete;
        }

        public function get oncomplete():Function {
            return this._oncomplete;
        }

        /**
         * This function is used to recenter map after dragging
         */
        private function done(xy:Pixel):void {
            if (this.dragging) {
                this.panMap(xy);
                this._dragging = false;
            }
        }

        private function panMap(xy:Pixel):void {
            this._dragging = true;
            var oldCenter:Location = this.map.center;
            var deltaX:Number = this._start.x - xy.x;
            var deltaY:Number = this._start.y - xy.y;
            var newPosition:Location = new Location(this._startCenter.lon + deltaX * this.map.resolution, this._startCenter.lat - deltaY * this.map.resolution, this._startCenter.projection);
            // If the new position equals the old center, stop here
            if (newPosition.equals(oldCenter)) {
                this.map.dispatchEvent(new MapEvent(MapEvent.MOVE_END, this.map));
                return;
            }
            // Try to set the new position as the center of the map
            //this.map.center=newPosition;
            this.map.moveTo(newPosition);

            // If the new position is invalid (see Map.setCenter for the
            // conditions), the center of the map is always the old one but the
            // bitmap that represents the map is centered to the new position.
            // We have to reset the bitmap position to the right center.

        /*			if (!this.map.isValidLocation(newPosition)) {
           this.map.moveTo(oldCenter);
         }*/

        }
    }
}

